<?php
namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Redis;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

class ZhengYuanService {

    //测试地址
    private static $host;//地址
    private static $app_id;//app_id
    private static $app_secret;//app_secret
    private static $shop_id;//商户id
    private static $org_code;//园区编号

    public function __construct()
    {
        self::$host = config('services.zy.host');

        self::$app_id = config('services.zy.appId');

        self::$app_secret = config('services.zy.appSecret');

        self::$shop_id = config('services.zy.shopId');

        self::$org_code = config('services.zy.orgCode');
    }

    /**
     * @notes 获取随机串
     * @return string
     * @author Evil丿
     * @date 2025/01/07 17:16
     */
    private function getNonce()
    {
        return time().rand(100000,999999);
    }

    /**
     * @notes 生成签名
     * @param $data
     * @return string
     * @author Evil丿
     * @date 2025/01/07 17:16
     */
    protected function makeSign($data)
    {
        ksort($data);
        reset($data);
        $tempStr = "";

        foreach ($data as $key => $value) {
            $tempStr .= $key . "=" . $value . "&";
        }
        $tempStr .= 'key=' . self::$app_id;

        return strtoupper(md5($tempStr));
    }

    /**
     * @notes 获取请求token
     * @return mixed
     * @author Evil丿
     * @date 2024/06/06 15:33
     */
    private function getRequestToken()
    {
        $token = Redis::get('zy:request_admin_token');

        if($token) return $token;

        $url = self::$host.'/api/web/token';

        $params = [
            'appid'     => self::$app_id,
            'appsecret' => self::$app_secret,
        ];

        $response = Http::retry(3, 1000)
            -> timeout(3)
            -> get($url, $params)
            -> throw()
            -> json();

        if(!$response) {
            throw new AccessDeniedHttpException('ZY服务请求失败');
        }

        $token = $response['accessToken'];

        Redis::setex('zy:request_admin_token', 60*60*2, $token);

        return $token;
    }

    /**
     * @notes 发起公共请求
     * @param $path
     * @param $data
     * @return mixed
     * @throws \Illuminate\Http\Client\RequestException
     * @author Evil丿
     * @date 2025/01/07 17:26
     */
    public function commonRequest($path, $data)
    {
        $url = self::$host . $path;

        $header = [
            'token'        => $this->getRequestToken(),
        ];

        $default_data = [
            'orgCode' => self::$org_code,
            'nonce' => $this->getNonce(),
        ];

        $data = array_merge($default_data, $data);

        $data['sign'] = $this->makeSign($data);

        $response = Http::retry(3, 1000)
            -> timeout(3)
            -> asForm()
            -> withHeaders($header)
            -> post($url, $data)
            -> throw()
            -> json();

        if(!$response) {
            throw new AccessDeniedHttpException('ZY服务请求失败');
        }

        if($response['code'] != 0) {
            throw new AccessDeniedHttpException($response['msg']);
        }

        if(!$response['data']) {
            $response['data'] = $response['code'];
        }

        return $response['data'];
    }

    /**
     * @notes 饭卡预下单
     * @param $memberId
     * @param $money
     * @return mixed
     * @author Evil丿
     * @date 2025/01/07 17:10
     */
    public function prePay($memberId, $money)
    {
        $path = '/openapi/common/infoqueryservice/prepay';

        $params = [
            'optType'    => 5,
            'memberId'   => $memberId,
            'monTrans'   => (string) $money, // 单位：元
            'shopId'     => self::$shop_id,
            'eWalletNum' => 1
        ];

        $res = $this -> commonRequest($path, $params);

        return $res;
    }

    /**
     * @notes 订单处理
     * @param $pay_id
     * @param $pay_no
     * @return mixed
     * @author Evil丿
     * @date 2025/01/07 17:16
     */
    public function orderHandle($pay_id, $pay_no)
    {
        $path = '/openapi/common/infoqueryservice/orderhandle';

        $params = [
            'payId'         => $pay_id, //云平台单号
            'payIsvTradeNo' => $pay_no, //商城订单号
            'payType'       => 2,
            'otherRecId'    => $pay_no,
        ];

        $res = $this -> commonRequest($path, $params);

        return $res;
    }

    /**
     * @notes 一卡通退款金额冲正
     * @param $pay_id
     * @param $pay_no
     * @param $amount
     * @return mixed
     * @author Evil丿
     * @date 2025/01/07 17:16
     */
    public function refundOrder($pay_id, $pay_no, $amount){
        $path = '/openapi/common/infoqueryservice/correct';

        $params = [
            'payId'        => $pay_id, //云平台单号
            'refundAmount' => (string) $amount, //退款金额 单位：元
            'outRefundNo'  => $pay_no,
        ];

        $res = $this -> commonRequest($path, $params);

        return $res;
    }
}
